import socket
from django.conf import settings
from satchmo_tryton import pysocket

__all__ = ['TrytonSyncFailed', 'Tryton']


class TrytonSyncFailed(Exception):

    def __init__(self, value):
        self.value = value

    def __str__(self):
        return 'Unable to sync with Tryton: %s' % repr(self.value)


class Tryton:
    MODEL_ADDRESS = 'party.address'
    MODEL_CONTACT_MECHANISM = 'party.contact_mechanism'
    MODEL_PARTY = 'party.party'
    MODEL_USER = 'res.user'

    def __init__(self):
        self._sock = None
        self.user_id = None
        self.session = None
        self.context = None

    def connect(self):
        """Handle Tryton NETRPC connection."""

        self._sock = pysocket.PySocket()

        try:
            self._sock.connect(settings.TRYTON_HOST, settings.TRYTON_PORT)
        except socket.error, e:
            raise TrytonSyncFailed(e)

        # Get user_id and session
        try:
            self._sock.send(
                (settings.TRYTON_DB, settings.TRYTON_USER,
                 settings.TRYTON_PASSWORD, 'common', 'db', 'login'))
            self.user_id, self.session = self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)

        # Get the user preferences to be used as the context to future
        # queries.
        try:
            self._sock.send(
                (settings.TRYTON_DB, self.user_id, self.session, 'model',
                 self.MODEL_USER, 'get_preferences', True, {}))
            self.context = self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)

    def search(self, model, domain, offset=0, limit=None, order=None,
               count=False):
        try:
            self._sock.send(
                (settings.TRYTON_DB, self.user_id, self.session, 'model',
                 model, 'search', domain, offset, limit, order, self.context,
                 count))
            return self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)

    def write(self, model, ids, values):
        try:
            self._sock.send(
                (settings.TRYTON_DB, self.user_id, self.session, 'model',
                 model, 'write', ids, values, self.context))
            return self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)

    def create(self, model, values):
        try:
            self._sock.send(
                (settings.TRYTON_DB, self.user_id, self.session, 'model',
                 model, 'create', values, self.context))
            return self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)

    def wizard_create(self, action):
        try:
            self._sock.send(
                (settings.TRYTON_DB, self.user_id, self.session, 'wizard',
                 action, 'create'))
            return self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)

    def wizard_execute(self, action, wiz_id, values):
        try:
            self._sock.send(
                (settings.TRYTON_DB, self.user_id, self.session, 'wizard',
                 action, 'execute', wiz_id, values, 'sync', self.context))
            return self._sock.receive()
        except socket.error, e:
            raise TrytonSyncFailed(e)
